home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 05 / 6 / DISK0564.ZIP / SOURCE.ARC / MODEM.C < prev    next >
C/C++ Source or Header  |  1988-07-09  |  22KB  |  877 lines

  1. /* modem program for MSDOS 2, assumes IBM compatibility at bios level */
  2.  
  3. /* for Aztec C86 v. 3.40a */
  4. /* by Jon Dart, 3012 Hawthorn St., San Diego, CA 92104 */
  5.  
  6. /* to make modem.exe:
  7.    cc modem
  8.    ln modem -lb -lm -lc  */
  9.    
  10. /* log:
  11.    Version 1.7 (25-Jan-87): more minor changes to XMODEM
  12.    Version 1.6 (11-Jan-87): minor cosmetic changes
  13.    Version 1.5 (30-Oct-86): improved XMODEM receive logic
  14.    Version 1.4 (14-Oct-86): SET no longer sets echo=on.
  15.    Version 1.3 (26-Jun-86): fixes bug in DIR routine
  16.    Version 1.26 (Apr 1986): XMODEM works
  17. */
  18.  
  19. #define Version "1.7 (25-Jan-87)"
  20. #include <stdio.h>
  21. #include <dioctl.h>
  22. #include <time.h>
  23. #include <fcntl.h>
  24. #include <ctype.h>
  25. #include "truth.h"
  26. #include "ascii.h"
  27. #include "fixpath.h"
  28.  
  29. #define skipsp(s,c) while (((c = *s) == SPACE) || (c==TAB)) s++
  30. #define chkabort(c) (keyin(&c) && (c==CAN))
  31.  
  32. #define WAITTIME 20
  33. #define TIME1 10  /* max time to wait for char. */
  34. #define MAXLINE 80
  35. #define MAXFILES 512 /* max number of files displayed by directory routine */
  36. #define NAMESIZE 13  /* size of a DOS file name (+1 for EOS) */
  37. #define PATHSIZE 65  /* size of a DOS2 path name (+1 for EOS) */
  38.  
  39. extern char *malloc();
  40. extern char *calloc();
  41. extern long lseek();
  42.  
  43. struct optstruc {
  44. int echo; /* <> 0 for echo */
  45. int baud; /* default baud rate */
  46. int db;   /* default data bits */
  47. int sb;   /* default stop bits */
  48. char parity;  /* default parity */
  49. int checksum; /* checksum mode */
  50. } options = {FALSE,1200,8,1,'N',FALSE};
  51.  
  52. int sendcksum; /* TRUE if checksum mode requested on send, FALSE if CRC */
  53. unsigned char *buf;
  54.  
  55. struct sgttyb stty;
  56.  
  57. waitch(c,t)
  58. /* waits for char. from host. If waiting time (t) exceeded, returns
  59.    function value FALSE */
  60. register char *c; int t;
  61. {
  62.     register int i; char cin; long oldtime, newtime;
  63.     int oldsec,newsec;
  64.  
  65.     i = 0; time(&oldtime);
  66.     oldsec = oldtime & 0x0f;
  67.     while (!receive(c)) {
  68.         if (i++>255) {
  69.             time(&newtime);
  70.             newsec = newtime & 0x0f;
  71.             if (newsec!=oldsec) {
  72.                 t -= 2;
  73.                 if (t<=0)
  74.                     return(FALSE);
  75.                 else
  76.                     oldsec = newsec;
  77.             }
  78.        }
  79.     }
  80.     /* got something */
  81.     /* putcb(*c); */
  82.     return(TRUE);
  83. }
  84.  
  85. show(c)
  86. char c;
  87. {
  88.     if ((c<32) && (c!=LF) && (c!=CR)) {
  89.         putchar('^'); putchar(c+'A'-1);
  90.     }
  91.     else if (c==LF) putchar('\n');
  92.     else putchar(c);
  93. }
  94.  
  95. showmode()
  96.  
  97. /* show currently enabled protocol */
  98.  
  99. {
  100.     if (options.checksum)
  101.         printf("CHECKSUM");
  102.     else
  103.         printf("CRC");
  104. }
  105.  
  106. crc(buf)
  107. unsigned char *buf;
  108.  
  109. /* compute a crc for the buffer */
  110.  
  111. {
  112. #define swap(x) ((x*256)+(x/256))
  113. #define lo(x) (x & 0xFF)
  114.     register unsigned int aa;
  115.     register int i;
  116.  
  117.     /* compute the crc. (Ref: Dr. Dobb's Journal, Feb. 1986, p. 80) */
  118.     aa = 0;
  119.     for (i=0;i<128;i++) {
  120.         aa = swap(aa) ^ buf[i];
  121.         aa = aa ^ (lo(aa) >> 4);
  122.         aa = aa ^ (swap(lo(aa)) << 4) ^ (lo(aa) << 5);
  123.     }
  124.     return(aa);
  125. }
  126.  
  127. cksum(buf)
  128. unsigned char *buf;
  129.  
  130. /* compute checksum for buffer */
  131.  
  132. {
  133.     unsigned int sum,i;
  134.  
  135.     sum = 0;
  136.     for (i=0;i<128;i++) {
  137.        sum = (sum + (*buf++ & 0377)) & 0377;
  138.     }
  139.     return(sum);
  140. }
  141.  
  142. char waitSOH(sec)
  143. int sec;
  144.  
  145. /* waits for SOH from remote, returns SOH or CAN if timeout or cancelled */
  146.  
  147. {
  148.      int errcnt, wtime, count, t, timeout, cans;
  149.      char c;
  150.  
  151.      t = 0; errcnt = 0;
  152.      for (;;) {
  153.          wtime = 10;  /* 10 sec to wait for 1st char */
  154.          cans = 0; /* counts cancel chars. recvd. */
  155.          count = 160; /* max. chars to gobble before SOH */
  156.          if (chkabort(c)) return(CAN);
  157.          if (sec==1) transmit((options.checksum) ? NAK : 'C');
  158.          do {
  159.              if ((timeout = !waitch(&c,wtime))==0) {
  160.                  /* got a char */
  161.                  if (c==EOT) { 
  162.                      if (!waitch(&c,5)) /* make sure no more chars. */
  163.                                     /* this reduces chance EOT is noise */
  164.                            return(EOT);
  165.                  }
  166.                  if (c==SOH) 
  167.                      return(c);
  168.                  else if (c==CAN) {
  169.                      if (++cans >= 5) return(c);
  170.                  }
  171.                  else if (wtime>1) { /* got some garbage */
  172.                      printf(" ++ Received %02x not SOH ++\n",c);
  173.                      wtime = 1; /* set timeout to 1 sec after 1st char recvd. */
  174.                  }
  175.                  else /* count chars recvd before SOH */
  176.                      count--;
  177.              }
  178.          } while ((!timeout) && (count>0));
  179.          errcnt++;
  180.          if (timeout && (wtime>1)) { /* no char. received */
  181.              t++;
  182.              printf(" ++ TIMEOUT - %d ++\n",t);
  183.          }
  184.          if (errcnt>=10)
  185.              return(CAN);
  186.          else if (errcnt==5) { /* switch modes */
  187.              options.checksum = !options.checksum;
  188.              printf("*** Switching to ");
  189.              showmode();
  190.              printf(" mode ***\n");
  191.          }
  192.      }
  193. }
  194.  
  195. get1sec(buf)
  196. register unsigned char *buf;
  197.  
  198. /* get 1 sector from remote, return count (0 if timeout) */
  199.  
  200. {
  201.      register int i;
  202.      int max, t, wtime;
  203.      unsigned char c;
  204.  
  205.      max = (options.checksum) ? 131 : 132;
  206.      wtime = 5;
  207.      for (i=0;i<max;i++) {
  208.           if (waitch(&c,wtime)) {
  209.               wtime = 2;
  210.               *buf++ = c;
  211.           }
  212.           else { /* timeout */
  213.               return(i);
  214.           }
  215.           if (i>129) wtime = 5; /* allow more time for checksum/crc */
  216.      }
  217.      return(i);
  218. }
  219.  
  220. openfile(filename)
  221. char *filename;
  222.  
  223. /* open file for receiving, return -1 if error, file descriptor if ok */
  224.  
  225. {
  226.     char sp[PATHSIZE],lip[PATHSIZE];
  227.     char c;
  228.     int fd;
  229.  
  230.     if (fixpath(filename,sp,lip)==TYPE_UFN) { /* file exists */
  231.         printf("%s exists. Overwrite [Y or N]? ",filename);
  232.         while (!keyin(&c) && ((c = toupper(c)!='Y') && (c!='N'))) ;
  233.         if (c=='N')
  234.             return(-1);
  235.     }
  236.     if ((fd = open(filename,O_WRONLY + O_TRUNC))==-1) {
  237.         printf("Can't open: %s\n",filename);
  238.         return(-1);
  239.     }
  240.     else
  241.         return(fd);
  242. }
  243.  
  244. goterror(sec,buf,count)
  245. unsigned int sec; unsigned char *buf; unsigned int count;
  246.  
  247. /* checks receive buffer, returns TRUE if error */
  248.  
  249. {
  250.     int x,cx;
  251.  
  252.     if ( ((sec & 0377) != buf[0])
  253.       || ((sec & 0377) != ~buf[1]) ) {
  254.         printf(" ++ Error in sector number ++\n");
  255.         return(TRUE);
  256.     }
  257.     if (count < ((options.checksum) ? 131 : 132)) {
  258.         printf(" ++ ERROR - Short block ++\n");
  259.         return(TRUE);
  260.     }
  261.     if (options.checksum) {
  262.         x = cksum(buf+2);
  263.         cx = buf[130];
  264.     }
  265.     else {
  266.         x = crc(buf+2);
  267.         cx = (buf[130]*256) + (buf[131] & 0377);
  268.     }
  269.     if (cx==x)
  270.         return(FALSE);
  271.     else {
  272.         printf(" ++ ");
  273.         showmode();
  274.         printf(" Error: Received %04x Computed %04x",cx,x);
  275.         printf(" ++\n");
  276.         return(TRUE);
  277.     }
  278. }
  279.  
  280. get(filename)
  281. char *filename;
  282.  
  283. /* get file from remote, using XMODEM protocol */
  284.  
  285. {
  286.      char c;
  287.      int fd;
  288.      unsigned int sec, count, errcnt;
  289.  
  290.      if ((fd = openfile(filename)) == -1)
  291.          return;
  292.      sec = 1;
  293.      putchar('\n');
  294.      showmode();
  295.      printf(" enabled.\nWaiting for first sector.\n");
  296.      errcnt = 0;
  297.      for (;;) {
  298.          c = waitSOH(sec);
  299.          if (c==EOT)
  300.             goto gotitall;
  301.          else if (c==CAN)
  302.             goto cancel;
  303.          /* got SOH */
  304.          printf("%cReceiving # %d ",CR,sec);
  305.          count = get1sec(buf);
  306.          if (goterror(sec,buf,count)) {
  307.              transmit(NAK);
  308.              errcnt++;
  309.              if (errcnt>10) goto cancel;
  310.          }
  311.          else {
  312.              if (write(fd,buf+2,128)!=128) {
  313.                  printf(" ++ DISK WRITE ERROR ++\n");
  314.                  goto cancel;
  315.              }
  316.              else {
  317.                  transmit(ACK);
  318.                  sec++;
  319.              }
  320.          }
  321.      }
  322.      close(fd);
  323.      return;
  324. cancel:
  325.      printf("\n ++ RECEIVE FILE CANCELLED ++\n");
  326.      close(fd);
  327.      unlink(filename);
  328.      printf(" ++ UNFINISHED FILE DELETED ++\n");
  329.      return;
  330. gotitall:
  331.      close(fd);
  332.      transmit(ACK);
  333.      printf("\nTransmission complete.\n");
  334.      return;
  335. }
  336.  
  337. char waitready()
  338.  
  339. /* waits for CRC or Checksum request from remote */
  340. /* returns 'C', NAK, or CAN */
  341.  
  342. {
  343.      char c;
  344.      int t;
  345.  
  346.      t = 0;
  347.      while (t<10) {
  348.          if (chkabort(c))
  349.              return(CAN);
  350.          if (waitch(&c,10)) { /* got a char */
  351.              if (c==NAK) {
  352.                  printf("Got checksum request.\n");
  353.                  sendcksum = TRUE;
  354.                  return(c);
  355.              }
  356.              else if (c=='C') {
  357.                  printf("Got CRC request.\n");
  358.                  sendcksum = FALSE;
  359.                  return(c);
  360.              }
  361.          }
  362.          else { /* timeout */
  363.              t++;
  364.              printf(" ++ TIMEOUT - %d ++\n",t);
  365.          }
  366.      }
  367.      return(CAN);
  368. }
  369.  
  370. send1sec(sec,buf)
  371. int sec; register unsigned char *buf;
  372.  
  373. /* transmit 1 sector to remote */
  374.  
  375. {
  376.     register unsigned int i;
  377.     unsigned int x;
  378.  
  379.     transmit(SOH);
  380.     transmit(sec & 0377);
  381.     transmit(~sec & 0377);
  382.     for (i=0;i<128;i++) {
  383.         transmit(buf[i]);
  384.     }
  385.     if (sendcksum) {
  386.         x = cksum(buf);
  387.         transmit(x & 0377);
  388.     }
  389.     else { /* CRC mode */
  390.         x = crc(buf);
  391.         transmit((x>>8) & 0377);
  392.         transmit(x & 0377);
  393.     }
  394. }
  395.  
  396. char waitACK(sec)
  397. int sec;
  398.  
  399. /* wait for ACK char from remote, after sending sec */
  400. /* returns ACK (if sector OK), NAK (if not OK) or CAN (if too many errors
  401.    or transmission cancelled by sender */
  402.  
  403. {
  404.     int count,errcnt,wtime;
  405.     char c;
  406.  
  407.     errcnt = 0; count = 160; wtime = 10; /* 10 secs. for 1st char */
  408.     do {
  409.         if (chkabort(c)) return(CAN);
  410.         c = CAN;
  411.         if (waitch(&c,wtime)) { /* got a char. */
  412.             wtime = 5;
  413.             if ((c==ACK) || (c==NAK))
  414.                 return(c);
  415.             else { /* garbage char */
  416.                 printf(" ++ %02x received not ACK ++\n",c);
  417.                 --count;
  418.             }
  419.         }
  420.         else  /* no char */
  421.             printf(" ++ TIMEOUT - no ACK - %d ++\n",++errcnt);
  422.     } while ((errcnt < 10) && (count>0));
  423.     return(CAN); /* too many errors */
  424. }
  425.  
  426.  
  427. send(filename)
  428. char *filename;
  429.  
  430. /* send file to remote system, using XMODEM protocol */
  431.  
  432. {
  433.     int fd, sectors, sec, i, n, x, retry;
  434.     char c;
  435.     long filesize;
  436.  
  437.     if ((fd = open(filename,O_RDONLY)) == -1) {
  438.         printf("\nCan't open: %s\n",filename);
  439.         return;
  440.     }
  441.     filesize = lseek(fd,0L,2);
  442.     sectors = filesize / 128;
  443.     if (filesize % 128) sectors++;
  444.     printf("File open to send. %d sectors, approx. %.1f minutes at %d baud.\n",
  445.            sectors,
  446.            ( (1.0*sectors)/(1.0*options.baud))*29.4, 
  447.            /* 29.4 is right for my system.  It depends
  448.               somewhat on disk speed */
  449.            options.baud);
  450.     lseek(fd,0L,0);
  451.     printf("Waiting ready signal.\n");
  452.     if (waitready()==CAN)
  453.         goto cancel;
  454.     sec = 1;
  455.     waitch(&c,1); /* wait 1 sec */
  456.     while (( n = read(fd,buf,128)) > 0) {
  457.         if (n<128) { /* pad out last buffer */
  458.             buf[n] = '\032'; /* control-Z */
  459.             for (i=n+1;i<128;i++) buf[i] = '\0';
  460.         }
  461.         printf("%cSending # %d ",CR,sec);
  462.         send1sec(sec,buf);
  463.         retry = 0;
  464.         do {
  465.             if ((c=waitACK(sec))==ACK) {
  466.                 sec++;
  467.                 break;
  468.             }
  469.             else if (c==CAN)
  470.                 goto cancel;
  471.             else if (c == NAK) {
  472.                 printf(" ++ NAK received not ACK - %d ++\n",++retry);
  473.                 if (retry<10) {
  474.                     printf("%cResending # %d",CR,sec);
  475.                     send1sec(sec,buf);
  476.                 }
  477.             }
  478.          } while (retry<10);
  479.          if (retry>=10) goto cancel;
  480.     }
  481.     /* normal exit */
  482.     printf("\nTransmission complete.\n");
  483.     transmit(EOT);
  484.     if (!waitch(&c,10) || (c!=ACK)) /* warn user about lack of ack */
  485.         printf("++ WARNING: Final ACK not received ++\n");
  486.     close(fd);
  487.     return;
  488. cancel:
  489.     printf("\n ++ SEND FILE CANCELLED. ++\n");
  490.     transmit(CAN);
  491.     close(fd);
  492.     return;
  493. }
  494.  
  495. toggle_echo()
  496. {
  497.     options.echo = !options.echo;
  498.     if (options.echo)
  499.         printf("\nEcho is ON\n");
  500.     else
  501.         printf("\nEcho is OFF\n");
  502. }
  503.  
  504. toggle_prot()
  505.  
  506. /* change protocol (CRC or Checksum) */
  507.  
  508. {
  509.      options.checksum = !options.checksum;
  510.      printf("\nMode is ");
  511.      showmode();
  512.      putchar('\n');
  513. }
  514.  
  515. show_options()
  516.  
  517. {
  518.     printf("\nCurrent option settings:\n\n");
  519.     printf("Baud rate  = %d\n",options.baud);
  520.     printf("Parity     = %c\n",options.parity);
  521.     printf("Data bits  = %d\n",options.db);
  522.     printf("Stop bits  = %d\n",options.sb);
  523.     printf("Echo       = %s\n",(options.echo) ? "ON" : "OFF");
  524.     printf("Protocol   = "); showmode(); putchar('\n');
  525. }
  526.  
  527. menu()
  528.  
  529. /* show available commands */
  530.  
  531. {
  532.     printf("\nM = Show this list                  DEL = Delete file\n");
  533.     printf("? = Show current options            DIR = Show directory\n");
  534.     printf("C = Toggle protocol (CRC/Checksum)  SET = Set communication params\n");
  535.     printf("E = Toggle echo\n");
  536.     printf("R = Receive File\n");
  537.     printf("S = Send File\n");
  538.     printf("T = Enter Terminal Mode\n");
  539.     printf("X = Exit to DOS\n");
  540. }
  541.  
  542. terminal()
  543.  
  544. /* terminal mode */
  545.  
  546. {
  547.     char c;
  548.     for (;;) {
  549.         if (keyin(&c)) {
  550.             if (c==CTRLE)
  551.                 break;
  552.             if (options.echo) putchar((c==CR) ? '\n' : c);
  553.             transmit(c);
  554.         }
  555.         if (receive(&c))
  556.             putchar(c);
  557.     }
  558. }
  559.  
  560. cmp(ptra,ptrb)
  561. char **ptra, **ptrb;
  562.  
  563. /* compare routine for qsort */
  564.  
  565. {
  566.     return(strcmp(*ptra,*ptrb));
  567. }
  568.  
  569. show1file(filename)
  570. char *filename;
  571.  
  572. {
  573.     int i;
  574.     char c;
  575.  
  576.     for (i=0;i<8;i++) {
  577.         if ( ((c = *filename)!='\0') && (c!='.') ) {
  578.            putchar(c);
  579.            filename++;
  580.         }
  581.         else
  582.            putchar(SPACE);
  583.     }
  584.     putchar('.');
  585.     if (*filename == '.')
  586.         filename++;
  587.     for (i=0;i<3;i++) {
  588.         if ((c = *filename)!='\0') {
  589.             putchar(c);
  590.             filename++;
  591.         }
  592.         else
  593.             putchar(SPACE);
  594.      }
  595. }
  596.  
  597. showfiles(dirptrs,count)
  598. char *dirptrs[]; int count;
  599.  
  600. /* display directory */
  601.  
  602. {
  603.     int i,n;
  604.  
  605.     n = 0;
  606.     for (i=0;i<count;i++) {
  607.         show1file(dirptrs[i]);
  608.         if (++n >= 5) {
  609.            putchar(NL);
  610.            n = 0;
  611.         }
  612.         else
  613.            printf(" | ");
  614.     }
  615. }
  616.  
  617. dodel(filespec)
  618. char *filespec;
  619. {
  620.     int type;
  621.     char sp[PATHSIZE],lip[PATHSIZE];
  622.     char c;
  623.  
  624.     skipsp(filespec,c);
  625.     if (c=='\0') {
  626.         printf("\nFile name required.\n");
  627.         return;
  628.     }
  629.     type = fixpath(filespec,sp,lip);
  630.     if (type == TYPE_UNK) {
  631.         printf("\nCan't find: %s\n",filespec);
  632.         return;
  633.     }
  634.     else if (type == TYPE_AFN) {
  635.         printf("\nWild cards not allowed.\n");
  636.         return;
  637.     }
  638.     else if ((type == TYPE_DIR) || (type==TYPE_DSP)) {
  639.         printf("\nCan't delete a directory.\n");
  640.         return;
  641.     }
  642.     else if (type == TYPE_DRV) {
  643.         printf("\nFile name required.\n");
  644.         return;
  645.     }
  646.     else {
  647.         if (unlink(filespec))
  648.            printf("\nCan't delete: %s\n",filespec);
  649.     }
  650. }
  651.  
  652. dodir(filespec)
  653. char *filespec;
  654.  
  655. /* display a sorted disk directory */
  656.  
  657. {
  658.     char c;
  659.     char filename[PATHSIZE], sp[PATHSIZE],lip[PATHSIZE];
  660.     char *dirptrs[MAXFILES];
  661.     char *dirbuf;
  662.     int attrib, count, n;
  663.     unsigned long freesp;
  664.     struct regstruc {
  665.        unsigned int ax,bx,cx,dx,si,di;
  666.     } inregs,outregs;
  667.  
  668.     if ((dirbuf = malloc(MAXFILES*NAMESIZE)) == NULL) {
  669.         printf("\nCan't allocate buffer space.\n");
  670.         return;
  671.     }
  672.     skipsp(filespec,c);
  673.     fixpath(filespec,sp,lip);
  674.     count = 0;
  675.     if (getfirst(sp,0x21,filename,&attrib)) {
  676.         do {
  677.             n = 13;
  678.             dirptrs[count] = dirbuf+(count*NAMESIZE);
  679.             cpycnt(filename,dirptrs[count],&n);
  680.             count++;
  681.         } while (getnext(filename,&attrib) && (count<MAXFILES-1));
  682.         qsort(dirptrs,count,2,cmp);
  683.         showfiles(dirptrs,count);
  684.         inregs.dx = (*(sp+1)==':') ? (int) (*sp-'A'+1) : 0;
  685.         doscall(0x36,&inregs,&outregs);
  686.         freesp = ((long) outregs.bx)*((long) outregs.cx)*((long) outregs.ax)/1024L;
  687.         if (count % 5) putchar(NL);
  688.         printf("(%ldK bytes free)\n",freesp);
  689.     }
  690.     else
  691.         printf("\nNo matching files.\n");
  692.     free(dirbuf);
  693. }
  694.  
  695. cmdsrc(cp)
  696. char *cp;
  697.  
  698. /* see if the string pointed at by cp matches a valid 3-letter command.
  699.    If so, return the command number.  If no match, return 0. */
  700.  
  701. {
  702.     static char cmdlist[] = "DELDIRSET";
  703.     char *cpp, *lp;
  704.     int n,j;
  705.  
  706.     n = 1; lp = cmdlist;
  707.     while (*lp) {
  708.         cpp = cp;
  709.         for (j=0;j<3;j++)
  710.             if (*(cpp+j) != *(lp+j)) break;
  711.         if (j==3)  /* got a match */
  712.             return(n);
  713.         else { /* try next 3 letters in cmdlist */
  714.             n++;
  715.             lp += 3;
  716.         }
  717.     }
  718.     return(0);
  719. }
  720.  
  721. char *getword(line,word,n)
  722. register char *line,*word; int n;
  723.  
  724. {
  725.     while ((!isspace(*line)) && (--n > 0))
  726.         *word++ = *line++;
  727.     *word = '\0';
  728.     return(line);
  729. }
  730.  
  731. set_error()
  732. {
  733.     printf("\nForm of SET command:\n");
  734.     printf("      SET Baud Parity DataBits StopBits\n");
  735.     printf("e.g.: SET 300 N 8 1\n");
  736. }
  737.  
  738. doset(cmdline)
  739. char *cmdline;
  740.  
  741. /* handle SET command */
  742.  
  743. {
  744.     struct optstruc newopts;
  745.     char c;
  746.     char s[10];
  747.     char *lp;
  748.  
  749.     newopts = options;  /*bug fix, 10-14-86 */
  750.     skipsp(cmdline,c);
  751.     if (c=='\0') {
  752.         set_error();
  753.         return;
  754.     }
  755.     lp = cmdline;
  756.     lp = getword(lp,s,10);
  757.     if (sscanf(s,"%d",&newopts.baud)!=1) {
  758.         printf("\nError in baud rate.\n");
  759.         set_error();
  760.         return;
  761.     }
  762.     skipsp(lp,c);
  763.     if (*lp)
  764.         newopts.parity = *lp++;
  765.     else
  766.         newopts.parity = options.parity;
  767.     skipsp(lp,c);
  768.     lp = getword(lp,s,10);
  769.     if (sscanf(s,"%d",&newopts.db)!=1)
  770.         newopts.db = options.db;
  771.     skipsp(lp,c);
  772.     lp = getword(lp,s,10);
  773.     if (sscanf(s,"%d",&newopts.sb)!=1)
  774.         newopts.sb = options.sb;
  775.     if (cominit(newopts.baud,newopts.parity,newopts.sb,newopts.db)==-1) {
  776.         printf("\nError in parameters.\n");
  777.         set_error();
  778.         cominit(options.baud,options.parity,options.sb,options.db);
  779.         return;
  780.     }
  781.     else
  782.         options = newopts;
  783. }
  784.  
  785. command(term,quit)
  786. int *term, *quit;
  787.  
  788. /* get command line from console and execute command */
  789.  
  790. {
  791.     unsigned char c, cmd;
  792.     unsigned char *cp;
  793.     unsigned char cmdline[128];
  794.  
  795.     gets(cmdline);
  796.     cp = cmdline;
  797.     /* make line upper-case */
  798.     while (*cp) { *cp = toupper(*cp); cp++; }
  799.     cp = cmdline;
  800.     skipsp(cp,cmd);
  801.     if (cmd=='\0')
  802.         return;
  803.     c = *(cp+1);
  804.     if (isspace(c) || (c=='\0')) { /* single-letter command */
  805.         cp++;
  806.         skipsp(cp,c); /* make cp point to 1st non-blank char. after command */
  807.         switch(cmd) {
  808.         case 'M': menu(); break;
  809.         case '?': show_options(); break;
  810.         case 'X': *quit = TRUE; break;
  811.         case 'T': *term = TRUE; 
  812.               printf("%s","\nEntering terminal mode.  Type CTRL-E to exit.\n\n");
  813.               break;
  814.         case 'R': get(cp); break;
  815.         case 'S': send(cp); break;
  816.         case 'E': toggle_echo(); break;
  817.         case 'C': toggle_prot(); break;
  818.         default:
  819.              putchar(BEL);
  820.         }
  821.     }
  822.     else { /* possible multi-letter command */
  823.         switch (cmdsrc(cp)) {
  824.             case 0: putchar(BEL); break;
  825.             case 1: dodel(cp+3); break;
  826.             case 2: dodir(cp+3); break;
  827.             case 3: doset(cp+3); break;
  828.         }
  829.     }
  830. }
  831.  
  832. main()
  833. {
  834.      int stat, ctlcstat, term, quit;
  835.      struct regstruc {
  836.         unsigned int ax,bx,cx,dx,si,di;
  837.      } inregs, outregs;
  838.      char *cmdline;
  839.  
  840.      clrscr();
  841.      printf("Modem Version %s ... by Jon Dart\n\n",Version);
  842.      stat = cominit(options.baud,options.parity,options.sb,options.db);
  843.      if ((stat & 0x10)==0)
  844.         printf("\n*** CTS not set ***\n");
  845.      if ((stat & 0x20)==0)
  846.         printf("\n*** DTR not set ***\n");
  847.      printf("\nType M for menu.\n");
  848.      cmdline = malloc(128);
  849.      buf = (unsigned char *) malloc(135);
  850.      if ((buf==NULL) || (cmdline==NULL)) {
  851.          printf("Out of memory.");
  852.          exit(1);
  853.      }
  854.      inregs.ax = 0;
  855.      doscall(0x33,&inregs,&outregs);  /* get current ^C status */
  856.      ctlcstat = outregs.dx; /* save it */
  857.      inregs.ax = 1;
  858.      inregs.dx = 0;
  859.      doscall(0x33,&inregs,&outregs); /* turn off ^C trapping */
  860.  
  861.      term = FALSE; quit = FALSE;
  862.      while (!quit) {
  863.          printf("\nCOMMAND>> ");
  864.          command(&term,&quit);
  865.          if (term) {
  866.              terminal();
  867.              term = FALSE;
  868.          }
  869.      }
  870.  
  871.      free(cmdline);
  872.      free(buf);
  873.      inregs.ax = 1;
  874.      inregs.dx = ctlcstat;
  875.      doscall(0x33,&inregs,&outregs); /* restore old ^C status */
  876. }
  877.